package com.vhans.db.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vhans.core.domain.*;
import com.vhans.core.redis.RedisService;
import com.vhans.core.strategy.context.SearchStrategyContext;
import com.vhans.core.utils.BeanCopyUtils;
import com.vhans.core.utils.CommonUtils;
import com.vhans.core.utils.StringUtils;
import com.vhans.core.web.model.vo.RecordSearchVO;
import com.vhans.db.mapper.*;
import com.vhans.db.model.dto.ConditionDTO;
import com.vhans.db.model.dto.DeleteDTO;
import com.vhans.db.model.dto.RecommendDTO;
import com.vhans.db.model.dto.TopDTO;
import com.vhans.db.model.dto.record.RecordDTO;
import com.vhans.db.model.vo.record.*;
import com.vhans.db.model.vo.tag.TagOptionVO;
import com.vhans.db.service.IAFileService;
import com.vhans.db.service.IBRecordService;
import com.vhans.db.service.IBTagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static com.vhans.core.constant.CommonConstant.FALSE;
import static com.vhans.core.constant.RedisConstant.*;
import static com.vhans.core.enums.FilePathEnum.RECORDI;
import static com.vhans.core.enums.FilePathEnum.RECORDV;

/**
 * 记录业务处理
 *
 * @author vhans
 */
@Service
public class BRecordServiceImpl extends ServiceImpl<BRecordMapper, BRecord> implements IBRecordService {

    @Autowired
    private BRecordMapper recordMapper;

    @Autowired
    private BTagTextMapper tagTextMapper;

    @Autowired
    private BTagMapper tagMapper;

    @Autowired
    private BUserCollectMapper userCollectMapper;

    @Autowired
    private BUserLikeMapper userLikeMapper;

    @Autowired
    private IBTagService tagService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IAFileService fileService;

    @Autowired
    private SearchStrategyContext searchStrategyContext;

    @Override
    public List<RecordVO> listRecordVO(ConditionDTO condition) {
        // 查询记录信息
        List<RecordVO> recordVOList = recordMapper.selectRecordVO(condition);
        // 封装记录信息
        recordVOList.forEach(item -> {
            // 查询浏览量
            Double viewCount = Optional.ofNullable(redisService.getZsetScore(RECORD_VIEW_COUNT, item.getId()))
                    .orElse((double) 0);
            // 查询点赞量
            Integer likeNumber = redisService.getHash(QUIZ_LIKE_COUNT, item.getId().toString());
            // 查询标签
            List<TagOptionVO> tags = Optional.ofNullable(tagMapper.selectTagByRecordId(item.getId())).orElse(new ArrayList<>());
            item.setViewCount(viewCount.intValue());
            // 设置当前点赞量为 持久点赞量 + 缓存点赞量
            item.setLikeNumber(item.getLikeNumber() + Optional.ofNullable(likeNumber).orElse(0));
            item.setTagVOList(tags);
        });
        return recordVOList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addRecord(RecordDTO record) {
        // 添加记录
        BRecord newRecord = BeanCopyUtils.copyBean(record, BRecord.class);
        if (StringUtils.isBlank(newRecord.getCover())) {
            SiteConfig siteConfig = redisService.getObject(SITE_SETTING);
            newRecord.setCover(siteConfig.getCover());
        }
        newRecord.setUserId(StpUtil.getLoginIdAsInt());
        recordMapper.insert(newRecord);
        // 保存记录标签
        saveRecordTag(record, newRecord.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteRecord(List<Integer> recordIdList) {
        // 删除记录标签
        tagTextMapper.delete(new LambdaQueryWrapper<BTagText>()
                .in(BTagText::getTypeId, recordIdList));
        // 删除记录
        recordMapper.deleteBatchIds(recordIdList);
    }

    @Transactional
    @Override
    public void updateRecordDelete(DeleteDTO delete) {
        // 批量更新记录删除状态
        List<BRecord> recordList = delete.getIdList()
                .stream()
                .map(id -> BRecord.builder()
                        .id(id)
                        .isDelete(delete.getIsDelete())
                        .isTop(FALSE)
                        .isRecommend(FALSE)
                        .likeNumber(0)
                        .collectNumber(0)
                        .build())
                .toList();
        this.updateBatchById(recordList);
        // 删除用户收藏和点赞
        List<Integer> recordIds = recordList.stream().map(BRecord::getId).toList();
        userCollectMapper.delete(new LambdaQueryWrapper<BUserCollect>()
                .in(BUserCollect::getTypeId, recordIds));
        userLikeMapper.delete(new LambdaQueryWrapper<BUserLike>()
                .in(BUserLike::getTypeId, recordIds));
    }

    @Override
    public void updateRecord(RecordDTO record) {
        // 修改记录
        BRecord newRecord = BeanCopyUtils.copyBean(record, BRecord.class);
        newRecord.setUserId(StpUtil.getLoginIdAsInt());
        recordMapper.updateById(newRecord);
        // 保存记录标签
        saveRecordTag(record, newRecord.getId());
    }

    @Override
    public RecordInfoVO editRecord(Integer recordId) {
        // 查询记录信息
        RecordInfoVO recordInfoVO = recordMapper.selectRecordInfoById(recordId);
        Assert.notNull(recordInfoVO, "没有该记录");
        // 转换图片格式
        if (StringUtils.isNotEmpty(recordInfoVO.getImages())) {
            recordInfoVO.setImgList(CommonUtils.castList(JSON.parseObject(recordInfoVO.getImages(), List.class), String.class));
        }
        // 查询记录标签名称
        List<String> tagNameList = tagMapper.selectTagNameByRecordId(recordId);
        recordInfoVO.setTagNameList(tagNameList);
        return recordInfoVO;
    }

    @Override
    public void updateRecordTop(TopDTO top) {
        // 修改记录置顶状态
        BRecord newRecord = BRecord.builder()
                .id(top.getId())
                .isTop(top.getIsTop())
                .build();
        recordMapper.updateById(newRecord);
    }

    @Override
    public void updateRecordRecommend(RecommendDTO recommend) {
        // 修改记录推荐状态
        BRecord newRecord = BRecord.builder()
                .id(recommend.getId())
                .isRecommend(recommend.getIsRecommend())
                .build();
        recordMapper.updateById(newRecord);
    }

    @Override
    public List<RecordSearchVO> listRecordsBySearch(String keyword) {
        return searchStrategyContext.executeRecordSearchStrategy(keyword);
    }

    @Override
    public List<RecordHomeListVO> listRecordHomeVO(String keyword) {
        // 查询首页记录
        List<RecordHomeListVO> records = recordMapper.listRecordHomeVO(keyword);
        records.forEach(record -> {
            // 查询浏览量
            Double viewCount = Optional.ofNullable(redisService.getZsetScore(RECORD_VIEW_COUNT, record.getId()))
                    .orElse((double) 0);
            // 查询点赞量
            Integer likeNumber = redisService.getHash(QUIZ_LIKE_COUNT, record.getId().toString());
            // 查询标签名
            List<String> tagNames = Optional.ofNullable(tagMapper.selectTagNameByRecordId(record.getId())).orElse(new ArrayList<>());
            record.setViewCount(viewCount.intValue());
            // 设置当前点赞量为 持久点赞量 + 缓存点赞量
            record.setLikeNumber(record.getLikeNumber() + Optional.ofNullable(likeNumber).orElse(0));
            record.setTagNameList(tagNames);
        });
        return records;
    }

    @Override
    public RecordHomeVO getRecordHomeById(Integer recordId) {
        // 查询记录信息
        RecordHomeVO record = recordMapper.selectRecordHomeById(recordId);
        if (StringUtils.isNull(record)) {
            return null;
        }
        // 转换图片格式
        if (StringUtils.isNotEmpty(record.getImages())) {
            record.setImgList(CommonUtils.castList(JSON.parseObject(record.getImages(), List.class), String.class));
        }
        // 浏览量+1
        redisService.incrZet(RECORD_VIEW_COUNT, recordId, 1D);
        // 查询上一篇记录
        RecordPaginationVO lastRecord = recordMapper.selectLastRecord(recordId);
        // 查询下一篇记录
        RecordPaginationVO nextRecord = recordMapper.selectNextRecord(recordId);
        record.setLastRecord(lastRecord);
        record.setNextRecord(nextRecord);
        // 查询浏览量
        Double viewCount = Optional.ofNullable(redisService.getZsetScore(RECORD_VIEW_COUNT, recordId))
                .orElse((double) 0);
        // 查询点赞量
        Integer likeNumber = redisService.getHash(QUIZ_LIKE_COUNT, recordId.toString());
        // 查询标签
        List<TagOptionVO> tags = Optional.ofNullable(tagMapper.selectTagByRecordId(recordId)).orElse(new ArrayList<>());
        record.setViewCount(viewCount.intValue());
        // 设置当前点赞量为 持久点赞量 + 缓存点赞量
        record.setLikeNumber(record.getLikeNumber() + Optional.ofNullable(likeNumber).orElse(0));
        record.setTagVOList(tags);
        return record;
    }

    @Override
    public List<RecordOverviewVO> listRecordOverviewVO() {
        return recordMapper.selectRecordList();
    }

    @Override
    public List<RecordRecommendVO> listRecordRecommendVO() {
        return recordMapper.selectRecordRecommend();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void collectRecord(Integer recordId) {
        BRecord record = recordMapper.selectOne(new LambdaQueryWrapper<BRecord>()
                .eq(BRecord::getId, recordId));
        Assert.notNull(record, "记录不存在");
        // 判断用户是否收藏
        List<Integer> collect = userCollectMapper.selectList(new LambdaQueryWrapper<BUserCollect>()
                        .select(BUserCollect::getUserId, BUserCollect::getTypeId)
                        .eq(BUserCollect::getUserId, StpUtil.getLoginIdAsInt()))
                .stream()
                .map(BUserCollect::getTypeId)
                .toList();
        if (collect.contains(recordId)) {
            // 取消收藏则删除用户的该收藏
            userCollectMapper.delete(new LambdaQueryWrapper<BUserCollect>()
                    .eq(BUserCollect::getUserId, StpUtil.getLoginIdAsInt())
                    .eq(BUserCollect::getTypeId, recordId));
            // 记录收藏数-1
            record.setCollectNumber(record.getCollectNumber() - 1);
        } else {
            // 收藏则添加用户的该收藏
            userCollectMapper.saveUserCollectRecord(StpUtil.getLoginIdAsInt(), recordId);
            // 记录收藏数+1
            record.setCollectNumber(record.getCollectNumber() + 1);
        }
        recordMapper.updateById(record);
    }

    @Override
    public String saveRecordImages(MultipartFile file) {
        // 上传图片
        return fileService.uploadStrategyFile(file, RECORDI.getPath(), "image");
    }

    @Override
    public String saveRecordVideo(MultipartFile file) {
        // 上传视频
        return fileService.uploadStrategyFile(file, RECORDV.getPath(), "video");
    }

    /**
     * 保存记录标签
     *
     * @param record   记录信息
     * @param recordId 记录id
     */
    private void saveRecordTag(RecordDTO record, Integer recordId) {
        // 删除记录标签
        tagTextMapper.delete(new LambdaQueryWrapper<BTagText>()
                .eq(BTagText::getTypeId, recordId));
        // 标签名列表
        List<String> tagNameList = record.getTagNameList();
        if (StringUtils.isNotEmpty(tagNameList)) {
            // 提供覆盖的标签
            List<Integer> coverTag = tagService.getCoverTag(tagNameList);
            // 将所有的标签绑定到记录标签关联表
            tagTextMapper.saveBatchRecordTag(recordId, coverTag);
        }
    }
}
